package cn.blackhole.simple.domain.factory;

import cn.blackhole.simple.common.enums.InterfaceType;
import cn.blackhole.simple.domain.Metric.service.MetricsCollector;
import cn.blackhole.simple.domain.Metric.service.impl.DefaultMetricsCollector;
import cn.blackhole.simple.domain.circuitBreaker.service.CircuitBreaker;
import cn.blackhole.simple.domain.circuitBreaker.service.FallbackHandler;
import cn.blackhole.simple.domain.circuitBreaker.service.impl.DefaultFallbackHandler;
import cn.blackhole.simple.domain.circuitBreaker.service.impl.NoOpCircuitBreaker;
import cn.blackhole.simple.domain.exception.service.ExceptionHandler;
import cn.blackhole.simple.domain.exception.service.impl.DefaultExceptionHandler;
import cn.blackhole.simple.domain.retry.service.RetryPolicy;
import cn.blackhole.simple.domain.retry.service.impl.NoRetryPolicy;
import lombok.Getter;
import lombok.Setter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class PolicyFactory {

    // 时效性
    @Setter
    @Getter
    private MetricsCollector metricsCollector = new DefaultMetricsCollector();

    // 新增熔断器和
    private final Map<InterfaceType, CircuitBreaker> circuitBreakers = new ConcurrentHashMap<>();

    // 降级注册
    private final Map<InterfaceType, FallbackHandler<?>> fallbackHandlers = new ConcurrentHashMap<>();

    private final Map<InterfaceType, RetryPolicy> retryPolicies = new ConcurrentHashMap<>();

    private final Map<InterfaceType, ExceptionHandler> exceptionHandlers = new ConcurrentHashMap<>();

    public void registerCircuitBreaker(InterfaceType type, CircuitBreaker breaker) {
        circuitBreakers.put(type, breaker);
    }

    public void registerFallbackHandler(InterfaceType type, FallbackHandler<?> handler) {
        fallbackHandlers.put(type, handler);
    }

    @SuppressWarnings("unchecked")
    public <T> FallbackHandler<T> getFallbackHandler(InterfaceType type) {
        return (FallbackHandler<T>) fallbackHandlers.getOrDefault(type, new DefaultFallbackHandler<>());
    }

    public CircuitBreaker getCircuitBreaker(InterfaceType type) {
        return circuitBreakers.getOrDefault(type, new NoOpCircuitBreaker());
    }

    public void registerRetryPolicy(InterfaceType type, RetryPolicy policy) {
        retryPolicies.put(type, policy);
    }

    public void registerExceptionHandler(InterfaceType type, ExceptionHandler handler) {
        exceptionHandlers.put(type, handler);
    }

    public RetryPolicy getRetryPolicy(InterfaceType type) {
        return retryPolicies.getOrDefault(type, new NoRetryPolicy());
    }

    public ExceptionHandler getExceptionHandler(InterfaceType type) {
        return exceptionHandlers.getOrDefault(type, new DefaultExceptionHandler());
    }

}